package com.rui.cn.consumer.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rui.cn.util.JsonMapperUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/** 
 * 通用redis缓存工具类 
 * @author evin
 * 
 */  
public class RedisHelper {  
      
	/**
	 * 删除缓存<br>
	 * 根据key精确匹配删除
	 * @param key
	 */
	@SuppressWarnings("unchecked")
	public static  void del(RedisTemplate<String, Object> redisTemplate, String... key) {
		if (key != null && key.length > 0) {
			if (key.length == 1) {
				redisTemplate.delete(key[0]);
			} else {
				redisTemplate.delete(CollectionUtils.arrayToList(key));
			}
		}
	}

	/**
	 * 批量删除<br>
	 * （该操作会执行模糊查询，请尽量不要使用，以免影响性能或误删）
	 * @param pattern
	 */
	public static  void batchDel(RedisTemplate<String, Object> redisTemplate,String... pattern) {
		for (String kp : pattern) {
			redisTemplate.delete(redisTemplate.keys(kp + "*"));
		}
	}

	/**
	 * 取得缓存（int型）
	 * @param key
	 * @return
	 */
	public static  Integer getInt(StringRedisTemplate stringRedisTemplate, String key) {
		String value = stringRedisTemplate.boundValueOps(key).get();
		if (StringUtils.isNotBlank(value)) {
			return Integer.valueOf(value);
		}
		return null;
	}

	/**
	 * 取得缓存（字符串类型）
	 * @param key
	 * @return
	 */
	public static  String getStr(StringRedisTemplate stringRedisTemplate,String key) {
		return stringRedisTemplate.boundValueOps(key).get();
	}

	/**
	 * 取得缓存（字符串类型）
	 * @param key
	 * @return
	 */
	public static String getStr(RedisTemplate<String, Object> redisTemplate,StringRedisTemplate stringRedisTemplate,String key, boolean retain) {
		String value = stringRedisTemplate.boundValueOps(key).get();
		if (!retain) {
			redisTemplate.delete(key);
		}
		return value;
	}

	/**
	 * 获取缓存<br>
	 * 注：基本数据类型(Character除外)，请直接使用get(String key, Class<T> clazz)取值
	 * @param key
	 * @return
	 */
	public static Object getObj(RedisTemplate<String, Object> redisTemplate,String key) {
		return redisTemplate.boundValueOps(key).get();
	}

	/**
	 * 获取缓存<br>
	 * 注：java 8种基本类型的数据请直接使用get(String key, Class<T> clazz)取值
	 * @param key
	 * @param retain 是否保留
	 * @return
	 */
	public static Object getObj(RedisTemplate<String, Object> redisTemplate,String key, boolean retain) {
		Object obj = redisTemplate.boundValueOps(key).get();
		if (!retain) {
			redisTemplate.delete(key);
		}
		return obj;
	}

	/**
	 * 获取缓存<br>
	 * 注：该方法暂不支持Character数据类型
	 * @param key key
	 * @param clazz 类型
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T get(RedisTemplate<String, Object> redisTemplate,String key, Class<T> clazz) {
		return (T) redisTemplate.boundValueOps(key).get();
	}

	/**
	 * 获取缓存json对象<br>
	 * @param key key
	 * @param clazz 类型
	 * @return
	 */
	public static <T> T getJson(StringRedisTemplate stringRedisTemplate,String key, Class<T> clazz) {
		return JsonMapperUtil.fromJsonString(stringRedisTemplate.boundValueOps(key)
				.get(), clazz);
	}

	/**
	 * 将value对象写入缓存
	 * @param key
	 * @param value
	 * @param time 失效时间(秒)
	 */
	public static void set(RedisTemplate<String, Object> redisTemplate, StringRedisTemplate stringRedisTemplate,String key,Object value, RedisExpireTime time) {
		if (value.getClass().equals(String.class)) {
			stringRedisTemplate.opsForValue().set(key, value.toString());
		} else if (value.getClass().equals(Integer.class)) {
			stringRedisTemplate.opsForValue().set(key, value.toString());
		} else if (value.getClass().equals(Double.class)) {
			stringRedisTemplate.opsForValue().set(key, value.toString());
		} else if (value.getClass().equals(Float.class)) {
			stringRedisTemplate.opsForValue().set(key, value.toString());
		} else if (value.getClass().equals(Short.class)) {
			stringRedisTemplate.opsForValue().set(key, value.toString());
		} else if (value.getClass().equals(Long.class)) {
			stringRedisTemplate.opsForValue().set(key, value.toString());
		} else if (value.getClass().equals(Boolean.class)) {
			stringRedisTemplate.opsForValue().set(key, value.toString());
		} else {
			redisTemplate.opsForValue().set(key, value);
		}
		if (time.getTime() > 0) {
			redisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
		}
	}

	/**
	 * 将value对象以JSON格式写入缓存
	 * @param key
	 * @param value
	 * @param time 失效时间(秒)
	 */
	public static void setJson(StringRedisTemplate stringRedisTemplate,String key, Object value, RedisExpireTime time) {
		stringRedisTemplate.opsForValue().set(key, JsonMapperUtil.toJsonString(value));
		if (time.getTime() > 0) {
			stringRedisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
		}
	}

	/**
	 * 更新key对象field的值
	 * @param key 缓存key
	 * @param field 缓存对象field
	 * @param value 缓存对象field值
	 */
	public static void setJsonField(StringRedisTemplate stringRedisTemplate,String key, String field, String value) {
		JSONObject obj = JSON.parseObject(stringRedisTemplate.boundValueOps(key).get());
		obj.put(field, value);
		stringRedisTemplate.opsForValue().set(key, obj.toJSONString());
	}

	/**
	 * 递减操作
	 * @param key
	 * @param by
	 * @return
	 */
	public static double decr(RedisTemplate<String, Object> redisTemplate,String key, double by) {
		return redisTemplate.opsForValue().increment(key, -by);
	}

	/**
	 * 递增操作
	 * @param key
	 * @param by
	 * @return
	 */
	public static double incr(RedisTemplate<String, Object> redisTemplate,String key, double by) {
		return redisTemplate.opsForValue().increment(key, by);
	}

	/**
	 * 获取double类型值
	 * @param key
	 * @return
	 */
	public static double getDouble(StringRedisTemplate stringRedisTemplate,String key) {
		String value = stringRedisTemplate.boundValueOps(key).get();
		if (StringUtils.isNotEmpty(value)) {
			return Double.valueOf(value);
		}
		return 0d;
	}

	/**
	 * 设置double类型值
	 * @param key
	 * @param value
	 * @param time 失效时间(秒)
	 */
	public static void setDouble(StringRedisTemplate stringRedisTemplate,String key, double value, RedisExpireTime time) {
		stringRedisTemplate.opsForValue().set(key, String.valueOf(value));
		if (time.getTime() > 0) {
			stringRedisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
		}
	}

	/**
	 * 设置double类型值
	 * @param key
	 * @param value
	 * @param time 失效时间(秒)
	 */
	public static void setInt(StringRedisTemplate stringRedisTemplate,String key, int value, RedisExpireTime time) {
		stringRedisTemplate.opsForValue().set(key, String.valueOf(value));
		if (time.getTime() > 0) {
			stringRedisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
		}
	}

	/**
	 * 将map写入缓存
	 * @param key
	 * @param map
	 * @param time 失效时间(秒)
	 */
	public static <T> void setMap(RedisTemplate<String, Object> redisTemplate,String key, Map<String, T> map, RedisExpireTime time) {
		redisTemplate.opsForHash().putAll(key, map);
		if (time.getTime() > 0) {
			redisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
		}
	}

	/**
	 * 将map写入缓存
	 * @param key
	 * @param time 失效时间(秒)
	 */
	@SuppressWarnings("unchecked")
	public static <T> void setMap(RedisTemplate<String, Object> redisTemplate,String key, T obj, RedisExpireTime time) {
		Map<String, String> map = (Map<String, String>) JsonMapperUtil.parseObject(obj, Map.class);
		redisTemplate.opsForHash().putAll(key, map);
		if (time.getTime() > 0) {
			redisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
		}
	}

	/**
	 * 向key对应的map中添加缓存对象
	 * @param key
	 * @param map
	 */
	public static <T> void addMap(RedisTemplate<String, Object> redisTemplate,String key, Map<String, T> map) {
		redisTemplate.opsForHash().putAll(key, map);
	}

	/**
	 * 向key对应的map中添加缓存对象
	 * @param key cache对象key
	 * @param field map对应的key
	 * @param value 值
	 */
	public static void addMap(RedisTemplate<String, Object> redisTemplate,String key, String field, String value) {
		redisTemplate.opsForHash().put(key, field, value);
	}

	/**
	 * 向key对应的map中添加缓存对象
	 * @param key cache对象key
	 * @param field map对应的key
	 * @param obj 对象
	 */
	public static <T> void addMap(RedisTemplate<String, Object> redisTemplate,String key, String field, T obj) {
		redisTemplate.opsForHash().put(key, field, obj);
	}

	/**
	 * 获取map缓存
	 * @param key
	 * @param clazz
	 * @return
	 */
	public static <T> Map<String, T> mget(RedisTemplate<String, Object> redisTemplate,String key, Class<T> clazz) {
		BoundHashOperations<String, String, T> boundHashOperations = redisTemplate.boundHashOps(key);
		return boundHashOperations.entries();
	}

	/**
	 * 获取map缓存
	 * @param key
	 * @param clazz
	 * @return
	 */
	public static <T> T getMap(RedisTemplate<String, Object> redisTemplate,String key, Class<T> clazz) {
		BoundHashOperations<String, String, String> boundHashOperations = redisTemplate.boundHashOps(key);
		Map<String, String> map = boundHashOperations.entries();
		return JsonMapperUtil.parseObject(map, clazz);
	}

	/**
	 * 获取map缓存中的某个对象
	 * @param key
	 * @param field
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getMapField(RedisTemplate<String, Object> redisTemplate,String key, String field, Class<T> clazz) {
		return (T) redisTemplate.boundHashOps(key).get(field);
	}

	/**
	 * 指定缓存的失效时间
	 * @author FangJun
	 * @date 2016年8月14日
	 * @param key 缓存KEY
	 * @param time 失效时间(秒)
	 */
	public static void expire(RedisTemplate<String, Object> redisTemplate,String key, RedisExpireTime time) {
		if (time.getTime() > 0) {
			redisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
		}
	}

	/**
	 * 短信缓存
	 * @param key
	 * @param value
	 * @param time
	 */
	public static void setIntForPhone(StringRedisTemplate stringRedisTemplate,String key, Object value, int time) {
		stringRedisTemplate.opsForValue().set(key, JsonMapperUtil.toJsonString(value));
		if (time > 0) {
			stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
		}
	}

	/**
	 * 模糊查询keys
	 * @param pattern
	 * @return
	 */
	public static Set<String> keys(RedisTemplate<String, Object> redisTemplate,String pattern) {
		return redisTemplate.keys(pattern);
	}
	
	/**
	 * 获取list集合
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> getList(RedisTemplate<String, Object> redisTemplate,String key ,Class<T> clazz){
		List<T> list = (List<T>) redisTemplate.boundListOps(key).range(0, -1);
		return list ;
	}
	
	/**
	 * 获取指定开始结束的list集合
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> getList(RedisTemplate<String, Object> redisTemplate,String key ,Class<T> clazz,Long start ,Long end){
		List<T> list = (List<T>) redisTemplate.boundListOps(key).range(start , end);
		return list ;
	}
	
	/**
	 * 添加list
	 * @param key
	 * @param list
	 */
	public static <T> void setList(RedisTemplate<String, Object> redisTemplate,String key,List<T> list ,RedisExpireTime time){
		for (T t : list) {
			redisTemplate.boundListOps(key).rightPush(t);
		}
		if (time.getTime() > 0) {
			redisTemplate.expire(key, time.getTime(), TimeUnit.SECONDS);
		}
	}
	/**
	 *@ 方法名：getListSize
	 *@ 参数：[redisTemplate, key]
	 *@ 返回值类型：Long
	 *@ 创建人：[zhang]
	 *@ 创建时间：2018/1/13 0013-下午 22:57
	 **/
	public static Long getListSize(RedisTemplate<String, Object> redisTemplate,String key){
		Long size = redisTemplate.boundListOps(key).size();
		return size;
	}
	
	/**
     * 右侧push数据
     * @param key
     * @param value
     * @return
     */
    public static Long rightPush(RedisTemplate<String, Object> redisTemplate, String key ,Object value) {
        return redisTemplate.boundListOps(key).rightPush(value);
    }
    
    /**
     * 左侧pop数据
     * @param key
     * @return
     */
    public static Object leftPop(RedisTemplate<String, Object> redisTemplate, String key) {
        return redisTemplate.boundListOps(key).leftPop();
    }
    
    /**
     * 获取第index位数据
     * @param redisTemplate
     * @param key
     * @param index
     * @return
     */
    public static Object index(RedisTemplate<String, Object> redisTemplate, String key,long index) {
        return redisTemplate.boundListOps(key).index(index) ;
    }
      
}  